/**
 * 版权所有 2009-2012山东新北洋信息技术股份有限公司
 * 保留所有权利。
 */
package com.linyaonan.leetcode.easy._892;

/**
 * 在 N * N 的网格上，我们放置一些 1 * 1 * 1  的立方体。
 * <p>
 * 每个值 v = grid[i][j] 表示 v 个正方体叠放在对应单元格 (i, j) 上。
 * <p>
 * 请你返回最终形体的表面积。
 * <p>
 *  
 * <p>
 * 示例 1：
 * <p>
 * 输入：[[2]]
 * 输出：10
 * 示例 2：
 * <p>
 * 输入：[[1,2],[3,4]]
 * 输出：34
 * 示例 3：
 * <p>
 * 输入：[[1,0],[0,2]]
 * 输出：16
 * 示例 4：
 * <p>
 * 输入：[[1,1,1],[1,0,1],[1,1,1]]
 * 输出：32
 * 示例 5：
 * <p>
 * 输入：[[2,2,2],[2,1,2],[2,2,2]]
 * 输出：46
 *  
 * <p>
 * 提示：
 * <p>
 * 1 <= N <= 50
 * 0 <= grid[i][j] <= 50
 *
 * @ProjectName: leetcode
 * @Package: com.linyaonan.leetcode.easy._892
 * @ClassName: SurfaceArea
 * @Author: linyaonan
 * @Date: 2020/1/14 17:25
 */
public class SurfaceArea {

    public int surfaceArea(int[][] grid) {
        int count = 0;
        int maxX = grid.length - 1;
        int maxY = grid[0].length - 1;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                int value = grid[i][j];
                // 上节点
                if (!hasNode(i - 1, j, maxX, maxY)) {
                    count += value;
                } else {
                    count += Math.max(value - grid[i - 1][j], 0);
                }
                // 下节点
                if (!hasNode(i + 1, j, maxX, maxY)) {
                    count += value;
                } else {
                    count += Math.max(value - grid[i + 1][j], 0);
                }
                // 左节点
                if (!hasNode(i, j - 1, maxX, maxY)) {
                    count += value;
                } else {
                    count += Math.max(value - grid[i][j - 1], 0);
                }
                // 右节点
                if (!hasNode(i, j + 1, maxX, maxY)) {
                    count += value;
                } else {
                    count += Math.max(value - grid[i][j + 1], 0);
                }
                // 俯视节点与底部节点
                if (value > 0) {
                    count += 2;
                }
            }
        }
        return count;
    }

    private boolean hasNode(int x, int y, int maxX, int maxy) {
        if (x < 0 || x > maxX) {
            return false;
        } else {
            return y >= 0 && y <= maxy;
        }
    }

}
